﻿using System;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.ComTypes;
using System.Text;

namespace Tsanie.ShellExt.Definitions
{

    // This namespace contains all the COM
    // interfaces required for the shell extesions

    #region - Structures -

    [StructLayout(LayoutKind.Sequential, Pack = 4)]
    public struct SIZE
    {
        public int cx;
        public int cy;
    }

    #endregion

    #region - IPropertyHandler Structs/Enums -

    /// <summary>
    /// Specifies the FMTID/PID identifier that programmatically identifies a property.
    /// </summary>
    /// <remarks> MSDN Reference: http://msdn.microsoft.com/en-us/library/bb773381.aspx </remarks>
    [StructLayout(LayoutKind.Sequential)]
    public struct PROPERTYKEY
    {
        /// <summary>
        /// A unique GUID for the property.
        /// </summary>
        public Guid fmtid;
        /// <summary>
        /// A property identifier (PID).
        /// </summary>
        public int pid;
    }

    /// <summary>
    /// Used by the <see cref="IPropertyStore.GetValue"/> and <see cref="IPropertyStore.SetValue"/> methods
    /// of <see cref="IPropertyStore"/> as the primary way to program item properties.
    /// </summary>
    /// <remarks> MSDN Reference: http://msdn.microsoft.com/en-us/library/aa380072.aspx </remarks>
    [StructLayout(LayoutKind.Sequential)]
    public struct PROPVARIANT
    {
        /// <summary>
        /// Value type tag.
        /// </summary>
        public short vt;
        /// <summary>
        /// Reserved for future use.
        /// </summary>
        public short wReserved1;
        /// <summary>
        /// Reserved for future use.
        /// </summary>
        public short wReserved2;
        /// <summary>
        /// Reserved for future use.
        /// </summary>
        public short wReserved3;
        /// <summary>
        /// Represents the variant data section.
        /// </summary>
        public VariantData Data;
    }

    /// <summary>
    /// Represents the variant data section of the PROPVARIANT structure.
    /// </summary>
    /// <remarks>
    /// This only provides variants for use within the context of MMDevice properties.
    /// </remarks>
    [StructLayout(LayoutKind.Explicit)]
    public struct VariantData
    {
        /// <summary>
        /// Represents the data as a boolean value.
        /// </summary>
        [FieldOffset(0)]
        public bool AsBoolean;
        /// <summary>
        /// Represents the data as a unsigned 32-bit integer.
        /// </summary>
        [FieldOffset(0)]
        public UInt32 AsUInt32;
        /// <summary>
        /// Represents the data as a unicode string pointer.
        /// </summary>
        [FieldOffset(0)]
        public IntPtr AsStringPtr;
        /// <summary>
        /// Represents the data as a pointer to a WAVEFORMATEX structure.
        /// </summary>
        [FieldOffset(4)]
        public IntPtr AsFormatPtr;
    }


    #endregion

    #region - IPropertyHandler -

    /// <summary>
    /// Exposes methods for enumerating, getting, and setting property values.
    /// </summary>
    /// <remarks>
    /// MSDN Reference: http://msdn.microsoft.com/en-us/library/bb761474.aspx
    /// Note: This item is defined in the Windows Property System API. (propsys.h)
    /// </remarks>
    [Guid("886d8eeb-8cf2-4446-8d02-cdba1dbdcf99")]
    [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    public interface IPropertyStore
    {

        /// <summary>
        /// Gets the number of properties attached to the file.
        /// </summary>
        /// <param name="propertyCount">Receives the property count.</param>
        /// <returns>An HRESULT code indicating whether the operation passed of failed.</returns>
        [PreserveSig]
        int GetCount([Out] [MarshalAs(UnmanagedType.U4)] out UInt32 propertyCount);

        /// <summary>
        /// Gets a property key from an item's array of properties.
        /// </summary>
        /// <param name="propertyIndex">The index of the property key in the array of <see cref="PROPERTYKEY"/> structures.</param>
        /// <param name="propertyKey">The unique identifier for a property.</param>
        /// <returns>An HRESULT code indicating whether the operation passed of failed.</returns>
        [PreserveSig]
        int GetAt([In] [MarshalAs(UnmanagedType.U4)] UInt32 propertyIndex, [Out] out PROPERTYKEY propertyKey);

        /// <summary>
        /// Gets data for a specific property.
        /// </summary>
        /// <param name="propertyKey">A <see cref="PROPERTYKEY"/> structure containing a unique identifier for the property in question.</param>
        /// <param name="value">Receives a <see cref="PROPVARIANT"/> structure that contains the property data.</param>
        /// <returns>An HRESULT code indicating whether the operation passed of failed.</returns>
        [PreserveSig]
        int GetValue([In] ref PROPERTYKEY propertyKey, [Out] out PROPVARIANT value);

        /// <summary>
        /// Sets a new property value, or replaces or removes an existing value.
        /// </summary>
        /// <param name="propertyKey">A <see cref="PROPERTYKEY"/> structure containing a unique identifier for the property in question.</param>
        /// <param name="value">A <see cref="PROPVARIANT"/> structure that contains the new property data.</param>
        /// <returns>An HRESULT code indicating whether the operation passed of failed.</returns>
        [PreserveSig]
        int SetValue([In] ref PROPERTYKEY propertyKey, [In] ref PROPVARIANT value);

        /// <summary>
        /// Saves a property change.
        /// </summary>
        /// <returns>An HRESULT code indicating whether the operation passed of failed.</returns>
        [PreserveSig]
        int Commit();

    }

    #endregion

    #region - IShellExtInit -

    /// <summary>
    /// The IShellExtInit interface is used by the shell to initialize shell extension objects.
    /// </summary>
    [ComImport]
    [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    [Guid("000214E8-0000-0000-c000-000000000046")]
    public interface IShellExtInit
    {
        /// <summary>
        /// The Initialize method is called when File Explorer is initializing a context menu extension,
        /// a property sheet extension, or a non-default drag-and-drop extension.
        /// </summary>
        /// <param name="pidlFolder">The pidl folder.</param>
        /// <param name="dataObject">The data object.</param>
        /// <param name="hkeyProgId">The hkey prog id.</param>
        void Initialize(IntPtr pidlFolder, [In] IDataObject dataObject, uint hkeyProgId);
    }

    #endregion

    //#region - IDataObject Enums/Structs -

    //public enum DATADIR
    //{
    //    DATADIR_GET = 1,
    //    DATADIR_SET = 2
    //}

    //public enum TYMED
    //{
    //    TYMED_HGLOBAL = 1,
    //    TYMED_FILE = 2,
    //    TYMED_ISTREAM = 4,
    //    TYMED_ISTORAGE = 8,
    //    TYMED_GDI = 16,
    //    TYMED_MFPICT = 32,
    //    TYMED_ENHMF = 64,
    //    TYMED_NULL = 0
    //}

    //public enum DVASPECT
    //{
    //    DVASPECT_CONTENT = 1,
    //    DVASPECT_THUMBNAIL = 2,
    //    DVASPECT_ICON = 4,
    //    DVASPECT_DOCPRINT = 8
    //}

    //public struct FORMATETC
    //{
    //    public short cfFormat;
    //    public int ptd;
    //    public DVASPECT dwAspect;
    //    public int lindex;
    //    public TYMED tymed;
    //}

    //public struct STGMEDIUM
    //{
    //    public TYMED tymed;
    //    public int data;
    //    [MarshalAs(UnmanagedType.IUnknown)]
    //    public Object pUnkForRelease;
    //}

    //#endregion

    //#region - IDataObject -

    //[ComImport]
    //[Guid("0000010e-0000-0000-C000-000000000046")]
    //[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    //public interface IDataObject
    //{

    //    void GetData(
    //        ref FORMATETC pformatetcIn,
    //        ref STGMEDIUM pmedium);

    //    void GetDataHere(
    //        ref FORMATETC pformatetc,
    //        ref STGMEDIUM pmedium);

    //    [PreserveSig]
    //    int QueryGetData(ref FORMATETC pformatetc);

    //    void GetCanonicalFormatEtc(
    //        ref FORMATETC pformatectIn,
    //        ref FORMATETC pformatetcOut);

    //    void SetData(
    //        ref FORMATETC pformatetc,
    //        ref STGMEDIUM pmedium,
    //        [MarshalAs(UnmanagedType.Bool)] Boolean fRelease);

    //    [return: MarshalAs(UnmanagedType.Interface)]
    //    Object EnumFormatEtc(DATADIR dwDirection);

    //    int DAdvise(
    //        ref FORMATETC pformatetc,
    //        int advf,
    //        [MarshalAs(UnmanagedType.Interface)] Object pAdvSink);

    //    void DUnadvise(int dwConnection);

    //    [return: MarshalAs(UnmanagedType.Interface)]
    //    Object EnumDAdvise();

    //}

    //#endregion

    #region - IExtractIcon Enums -

    [Flags]
    public enum IconHandlerFlags
    {
        Open = 0x1,
        ForShell = 0x2,
        Async = 0x20,
        DefaultIcon = 0x40,
        ForShortcut = 0x80
    }
    [Flags]
    public enum IconHandlerReturnFlags
    {
        SimulateDoc = 0x1,
        PerInstance = 0x2,
        PerClass = 0x4,
        NotFilename = 0x8,
        DontCache = 0x10
    }

    #endregion

    #region - IExtractIcon -

    [Guid("000214EB-0000-0000-C000-000000000046")]
    [ComImport]
    [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    public interface IExtractIconA
    {

        IconHandlerReturnFlags GetIconLocation(
            [In] IconHandlerFlags uFlags,
            [In, Out, MarshalAs(UnmanagedType.LPStr)] StringBuilder szIconFile,
            [In] int cchMax,
            [In, Out] ref int piIndex);

        void Extract(
            [In, MarshalAs(UnmanagedType.LPStr)] String pszFile,
            [In] int nIconIndex,
            [In, Out] ref IntPtr phiconLarge,
            [In, Out] ref IntPtr phiconSmall,
            [In] int nIconSize);

    }

    [Guid("000214FA-0000-0000-C000-000000000046")]
    [ComImport]
    [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    public interface IExtractIconW
    {

        IconHandlerReturnFlags GetIconLocation(
            [In] IconHandlerFlags uFlags,
            [In, Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder szIconFile,
            [In] int cchMax,
            [In, Out] ref int piIndex);

        void Extract(
            [In, MarshalAs(UnmanagedType.LPWStr)] String pszFile,
            [In] int nIconIndex,
            [In, Out] ref IntPtr phiconLarge,
            [In, Out] ref IntPtr phiconSmall,
            [In] int nIconSize);

    }

    #endregion

    #region - IExtractImage Enums -

    [Flags]
    public enum ThumbnailFlags
    {
        Async = 0x1,       // ask the extractor if it supports ASYNC extract (free threaded)
        Cache = 0x2,       // returned from the extractor if it does NOT cache the thumbnail
        Aspect = 0x4,      // passed to the extractor to beg it to render to the aspect ratio of the supplied rect
        OffLine = 0x8,     // if the extractor shouldn//t hit the net to get any content neede for the rendering
        Gleam = 0x10,      // does the image have a gleam ? this will be returned if it does
        Screen = 0x20,     // render as if for the screen  (this is exlusive with IEIFLAG_ASPECT )
        OrigSize = 0x40    // render to the approx size passed, but crop if neccessary
    }

    #endregion

    #region - IExtractImage -

    [Guid("BB2E617C-0920-11d1-9A0B-00C04FC2D6C1")]
    [ComImport]
    [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    public interface IExtractImage
    {

        void GetLocation(
            [In, Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszPathBuffer,
            [In] int cch,
            [Out] out int pdwPriority,
            [In] ref SIZE prgSize,
            [In] int dwRecClrDepth,
            [In] ref ThumbnailFlags pdwFlags);

        IntPtr Extract();

    }

    [Guid("953BB1EE-93B4-11d1-98A3-00C04FB687DA")]
    [ComImport]
    [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    public interface IExtractImage2
    {

        void GetLocation(
            [In, Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszPathBuffer,
            [In] int cch,
            [Out] out int pdwPriority,
            [In] ref SIZE prgSize,
            [In] int dwRecClrDepth,
            [In] ref ThumbnailFlags pdwFlags);

        IntPtr Extract();

        long GetDateStamp();

    }

    #endregion

    #region - IContextMenu Enums/Structs -

    /// <summary>
    /// Flag options for the IContextMenu interface.
    /// </summary>
    [Flags]
    public enum QueryContextMenuOptions
    {
        /// <summary>
        /// Indicates normal operation. A shortcut menu extension, namespace extension,
        /// or drag-and-drop handler can add all menu items. (CMF_NORMAL).
        /// </summary>
        Normal = 0,
        /// <summary>
        /// The user is activating the default action, typically by double-clicking.
        /// This flag provides a hint for the shortcut menu extension to add nothing if it 
        /// does not modify the default item in the menu. A shortcut menu extension or
        /// drag-and-drop handler should not add any menu items if this value is specified.
        /// A namespace extension should at most add only the default item. (CMF_DEFAULTONLY).
        /// </summary>
        DefaultOnly = 1,
        /// <summary>
        /// The shortcut menu is that of a shortcut file (normally, a .lnk file).
        /// Shortcut menu handlers should ignore this value. (CMF_VERBSONLY).
        /// </summary>
        VerbsOnly = 2,
        /// <summary>
        /// The Windows Explorer tree window is present. (CMF_EXPLORE).
        /// </summary>
        Explore = 4,
        /// <summary>
        /// This flag is set for items displayed in the Send To menu.
        /// Shortcut menu handlers should ignore this value. (CMF_NOVERBS).
        /// </summary>
        NoVerbs = 8,
        /// <summary>
        /// The calling application supports renaming of items.
        /// A shortcut menu or drag-and-drop handler should ignore this flag.
        /// A namespace extension should add a Rename item to the menu if applicable. (CMF_CANRENAME).
        /// </summary>
        CanRename = 0x10,
        /// <summary>
        /// No item in the menu has been set as the default.
        /// A drag-and-drop handler should ignore this flag.
        /// A namespace extension should not set any of the menu items as the default. (CMF_NODEFAULT)
        /// </summary>
        NoDefault = 0x20,
        CMF_INCLUDESTATIC = 0x40,
        CMF_RESERVED = unchecked((int)0xFFFF0000)
    }

    [Flags]
    public enum InvokeCommandMask
    {
        CMIC_MASK_HOTKEY = 0x20,
        CMIC_MASK_ICON = 0x10,
        CMIC_MASK_FLAG_NO_UI = 0x400,
        CMIC_MASK_UNICODE = 0x4000,
        CMIC_MASK_NO_CONSOLE = 0x8000,
        CMIC_MASK_ASYNCOK = 0x100000,
        CMIC_MASK_PTINVOKE = 0x20000000,
        CMIC_MASK_SHIFT_DOWN = 0x10000000,
        CMIC_MASK_CONTROL_DOWN = 0x20000000
    }

    /// <summary>
    /// Flags specifying the information to return.
    /// </summary>
    public enum GetCommandStringOptions
    {
        /// <summary>
        /// Sets pszName to an ANSI string containing the help text for the command (GCS_VERBA).
        /// </summary>
        CanonicalVerbAnsi = 0x0,
        /// <summary>
        /// Sets pszName to a Unicode string containing the language-independent command name for the menu item (GCS_VERBW).
        /// </summary>
        CanonicalVerb = 0x4,
        /// <summary>
        /// Sets pszName to a Unicode string containing the help text for the command (GCS_HELPTEXTW).
        /// </summary>
        HelpText = 0x5,
        /// <summary>
        /// Returns S_OK if the menu item exists, or S_FALSE otherwise.
        /// </summary>
        Validate = 0x6
    }

    /// <summary>
    /// Contains information needed by IContextMenu::InvokeCommand to 
    /// invoke a shortcut menu command (CMINVOKECOMMANDINFO).
    /// </summary>
    [StructLayout(LayoutKind.Sequential)]
    public struct InvokeCommandInfo
    {
        /// <summary>
        /// The size of this structure, in bytes (cbSize).
        /// </summary>
        public int cbSize;           // sizeof(CMINVOKECOMMANDINFO)
        /// <summary>
        /// Any combination of CMIC_MASK_*.
        /// </summary>
        public InvokeCommandMask fMask;
        /// <summary>
        /// Might be NULL, indicating no owner window (hwnd).
        /// </summary>
        public IntPtr parentWindow;
        /// <summary>
        /// either a string or MAKEINTRESOURCE(idOffset).
        /// </summary>
        public IntPtr lpVerb;
        /// <summary>
        /// might be NULL (indicating no parameter).
        /// </summary>
        public string lpParameters;
        /// <summary>
        /// Might be NULL (indicating no specific directory).
        /// </summary>
        public string lpDirectory;
        /// <summary>
        /// one of SW_ values for ShowWindow() API.
        /// </summary>
        public int nShow;
        /// <summary>
        /// An optional keyboard shortcut to assign to any application activated by the command.
        /// If the fMask parameter does not specify CMIC_MASK_HOTKEY, this member is ignored.
        /// </summary>
        public int dwHotKey;
        /// <summary>
        /// An icon to use for any application activated by the command.
        /// If the fMask member does not specify CMIC_MASK_ICON, this member is ignored.
        /// </summary>
        public IntPtr hIcon;
    }

    #endregion

    #region - IContextMenu -

    /// <summary>
    /// Exposes methods that either create or merge a shortcut menu associated with a Shell object.
    /// Allows client objects to handle messages associated with owner-drawn menu items and extends
    /// IContextMenu2 by accepting a return value from that message handling.
    /// </summary>
    [ComImport]
    [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    [Guid("000214E4-0000-0000-c000-000000000046")]
    public interface IContextMenu
    {
        /// <summary>
        /// Queries the context menu (from IContextMenu).
        /// </summary>
        /// <param name="menuHandle">A handle to the shortcut menu. The handler should specify this handle when adding menu items (hmenu).</param>
        /// <param name="position">The zero-based position at which to insert the first new menu item (indexMenu).</param>
        /// <param name="firstCommandId">The minimum value that the handler can specify for a menu item identifier (idCmdFirst).</param>
        /// <param name="lastCommandId">The maximum value that the handler can specify for a menu item identifier (idCmdLast).</param>
        /// <param name="flags">Optional flags that specify how the shortcut menu can be changed (uFlags).</param>
        /// <returns>
        /// If successful, returns an HRESULT value that has its severity value set to SEVERITY_SUCCESS and 
        /// its code value set to the offset of the largest command identifier that was assigned.
        /// </returns>
        [PreserveSig]
        [return: MarshalAs(UnmanagedType.Error)]
        int QueryContextMenu(IntPtr menuHandle, uint position, uint firstCommandId, uint lastCommandId, QueryContextMenuOptions flags);

        /// <summary>
        /// Carries out the command associated with a shortcut menu item (from IContextMenu).
        /// </summary>
        /// <param name="invokeCommandInfo">The invoke command info.</param>
        void InvokeCommand([In] ref InvokeCommandInfo invokeCommandInfo);

        /// <summary>
        /// Gets information about a shortcut menu command, including the help string and the
        /// language-independent, or canonical, name for the command (from IContextMenu).
        /// </summary>
        /// <param name="idCommand">Menu command identifier offset.</param>
        /// <param name="flags">Flags specifying the information to return.</param>
        /// <param name="reserved">Reserved. Applications must specify NULL when calling this method and handlers must ignore this parameter when called.</param>
        /// <param name="name">The reference of the buffer to receive the null-terminated string being retrieved.</param>
        /// <param name="cch">Size of the buffer, in characters, to receive the null-terminated string.</param>
        /// <returns>If the method succeeds, it returns S_OK. Otherwise, it returns an HRESULT error code.</returns>
        [PreserveSig]
        [return: MarshalAs(UnmanagedType.Error)]
        int GetCommandString(IntPtr idCommand, GetCommandStringOptions flags, int reserved, IntPtr name, int cch);
    }

    /// <summary>
    /// Exposes methods that either create or merge a shortcut menu associated with a Shell object.
    /// Allows client objects to handle messages associated with owner-drawn menu items and extends
    /// IContextMenu2 by accepting a return value from that message handling.
    /// </summary>
    [ComImport]
    [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    [Guid("000214F4-0000-0000-c000-000000000046")]
    public interface IContextMenu2
    {

        [PreserveSig]
        [return: MarshalAs(UnmanagedType.Error)]
        int QueryContextMenu(IntPtr menuHandle, uint position, uint firstCommandId, uint lastCommandId, QueryContextMenuOptions flags);

        void InvokeCommand([In] ref InvokeCommandInfo invokeCommandInfo);

        [PreserveSig]
        [return: MarshalAs(UnmanagedType.Error)]
        int GetCommandString(IntPtr idCommand, GetCommandStringOptions flags, int reserved, IntPtr name, int cch);

        /// <summary>
        /// Enables client objects of the IContextMenu interface to handle messages
        /// associated with owner-drawn menu items (from IContextMenu2).
        /// </summary>
        /// <param name="message">The message to be processed.</param>
        /// <param name="wParam">Additional message information. The value of the wParam parameter depends on the value of the message parameter.</param>
        /// <param name="lParam">Additional message information. The value of the lParam parameter depends on the value of the message parameter.</param>
        void HandleMenuMsg(uint message, IntPtr wParam, IntPtr lParam);

    }

    /// <summary>
    /// Exposes methods that either create or merge a shortcut menu associated with a Shell object.
    /// Allows client objects to handle messages associated with owner-drawn menu items and extends
    /// IContextMenu2 by accepting a return value from that message handling.
    /// </summary>
    [ComImport]
    [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    [Guid("bcfce0a0-ec17-11d0-8d10-00a0c90f2719")]
    public interface IContextMenu3
    {

        [PreserveSig]
        [return: MarshalAs(UnmanagedType.Error)]
        int QueryContextMenu(IntPtr menuHandle, uint position, uint firstCommandId, uint lastCommandId, QueryContextMenuOptions flags);

        void InvokeCommand([In] ref InvokeCommandInfo invokeCommandInfo);

        [PreserveSig]
        [return: MarshalAs(UnmanagedType.Error)]
        int GetCommandString(IntPtr idCommand, GetCommandStringOptions flags, int reserved, IntPtr name, int cch);

        void HandleMenuMsg(uint message, IntPtr wParam, IntPtr lParam);

        /// <summary>
        /// Allows client objects of the IContextMenu3 interface to handle messages associated with owner-drawn menu items.
        /// </summary>
        /// <param name="message">The message to be processed.</param>
        /// <param name="wParam">Additional message information. The value of the wParam parameter depends on the value of the message parameter.</param>
        /// <param name="lParam">Additional message information. The value of the lParam parameter depends on the value of the message parameter.</param>
        /// <param name="result">A pointer to the result.</param>
        void HandleMenuMsg2(uint message, IntPtr wParam, IntPtr lParam, IntPtr result);

    }

    #endregion

    #region - IQueryInfo Enums -

    /// <summary>
    /// Flags that define the handling of the item when retrieving the info tip text.
    /// </summary>
    [Flags]
    public enum InfoTipOptions
    {
        /// <summary>
        /// No special handling. QITIPF_DEFAULT (0).
        /// </summary>
        Default = 0,
        /// <summary>
        /// Provide the name of the item in ppwszTip rather than the info tip text. QITIPF_USENAME (1).
        /// </summary>
        UseName = 1,
        /// <summary>
        /// If the item is a shortcut, retrieve the info tip text of the shortcut rather than its target. QITIPF_LINKNOTARGET (2).
        /// </summary>
        LinkNoTarget = 2,
        /// <summary>
        /// If the item is a shortcut, retrieve the info tip text of the shortcut's target. QITIPF_LINKUSETARGET (4).
        /// </summary>
        LinkUseTarget = 4,
        /// <summary>
        /// Search the entire namespace for the information. This may result in a delayed response time. QITIPF_USESLOWTIP (8).
        /// </summary>
        UseSlowTip = 8,
        /// <summary>
        /// Put the info tip on a single line (only Windows Vista and later). QITIPF_SINGLELINE (10).
        /// </summary>
        SingleLine = 0x10
    }

    [Flags]
    public enum InfoFlags
    {
        None = 0,
        Cached = 0x1,
        DontExpandFolder = 0x2
    }

    #endregion

    #region - IQueryInfo -

    /// <summary>
    /// Exposes methods that the Shell uses to retrieve flags and info tip information for an item that resides 
    /// in an IShellFolder implementation. Info tips are usually displayed inside a ToolTip control.
    /// </summary>
    [ComImport]
    [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    [Guid("00021500-0000-0000-C000-000000000046")]
    public interface IQueryInfo
    {

        /// <summary>
        /// Gets the info tip text for an item.
        /// </summary>
        /// <param name="options">Flags directing the handling of the item from which you're retrieving the info tip text. This value is commonly zero (QITIPF_DEFAULT).</param>
        /// <param name="text">The info tip text.</param>
        void GetInfoTip([In] InfoTipOptions options, [Out, MarshalAs(UnmanagedType.LPWStr)] out string text);

        /// <summary>
        /// Gets the information flags for an item.
        /// </summary>
        /// <param name="options">The options.</param>
        void GetInfoFlags([Out] out InfoFlags flag);

    }

    #endregion

    #region - IShellPropSheetExt Delegates -

    /// <summary>
    /// Callback, passed to 'AddPages'.
    /// </summary>
    public delegate bool AddPageDelegate(IntPtr hPage, IntPtr lParam);

    #endregion

    #region - IShellPropSheetExt -

    /// <summary>
    /// Exposes methods that allow a property sheet handler to add or replace pages in the property sheet displayed for a file object.
    /// </summary>
    [ComImport]
    [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    [Guid("000214E9-0000-0000-C000-000000000046")]
    public interface IShellPropSheetExt
    {

        /// <summary>
        /// Adds one or more pages to a property sheet that the Shell displays for a file object.
        /// The Shell calls this method for each property sheet handler registered to the file type.
        /// </summary>
        /// <param name="addPageFunction">
        /// A pointer to a function that the property sheet handler calls to add a page to the property sheet.
        /// The function takes a property sheet handle returned by the CreatePropertySheetPage function and
        /// the lParam parameter passed to this method.</param>
        /// <param name="lParam">Handler-specific data to pass to the function pointed to by pfnAddPage.</param>
        /// <returns>If successful, returns a one-based index to specify the page that should be initially displayed.</returns>
        [PreserveSig]
        [return: MarshalAs(UnmanagedType.Error)]
        int AddPages([MarshalAs(UnmanagedType.FunctionPtr)] AddPageDelegate addPageFunction, IntPtr lParam);

        /// <summary>
        /// Replaces a page in a property sheet for a Control Panel object.
        /// </summary>
        /// <param name="pageId">Windows XP and earlier: a type EXPPS identifier of the page to replace.</param>
        /// <param name="replaceWithFunction">
        /// A pointer to a function that the property sheet handler calls to replace a page to the property sheet.
        /// The function takes a property sheet handle returned by the CreatePropertySheetPage function and
        /// the lParam parameter passed to the ReplacePage method.</param>
        /// <param name="lParam">The parameter to pass to the function specified by the pfnReplacePage parameter.</param>
        void ReplacePage(uint pageId, IntPtr replaceWithFunction, IntPtr lParam);

    }

    #endregion

#if IDropTarget

    #region - IDropTarget Enums -

    [Flags]
    public enum DragDropEffects {
        None = 0,
        Copy = 1,
        Move = 2,
        Link = 4,
        Scroll = unchecked((int)0x80000000),
        All = unchecked((int)0x80000003)
    }

    [Flags]
    public enum KeyStates {
        LeftButton = 1,
        RightButton = 2,
        Shift = 4,
        Control = 8,
        MedButton = 0x10,
        Alt = 0x20
    }

    #endregion

    #region - IDropTarget -

    [ComImport]
    [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    [Guid("00000122-0000-0000-C000-000000000046")]
    public interface IDropTarget {

        void DragEnter(
            IDataObject pDataObj,
            KeyStates grfKeyState,
            int ptX,
            int ptY,
            ref DragDropEffects pdwEffect);

        void DragOver(
            KeyStates grfKeyState,
            int ptX,
            int ptY,
            ref DragDropEffects pdwEffect);

        void DragLeave();

        void Drop(
            IDataObject pDataObj,
            KeyStates grfKeyState,
            int ptX,
            int ptY,
            ref DragDropEffects pdwEffect);

    }

    #endregion

#endif

#if IShellExecuteHook

    #region - IShellExecuteHook Enums/Structs -

    [Flags]
    public enum ShellExecuteHookFlags {
        ClassName = 0x1,
        ClassKey = 0x3,
        IdList = 0x4,
        InvokeIdList = 0xC,
        Icon = 0x10,
        HotKey = 0x20,
        NoCloseProcess = 0x40,
        ConnectNetDrv = 0x80,
        DdeWait = 0x100,
        DoEnvSubst = 0x200,
        NoUI = 0x400,
        Unicode = 0x4000,
        NoConsole = 0x8000,
        AsynOK = 0x100000,
        hMonitor = 0x200000,
    }

    public struct SHELLEXECUTEINFO_ {
        public int cbSize;
        public ShellExecuteHookFlags fMask;
        public IntPtr hWnd;
        public IntPtr lpVerb;
        public IntPtr lpFile;
        public IntPtr lpParameters;
        public IntPtr lpDirectory;
        public int nShow;
        public IntPtr hInstApp;
        public IntPtr lpIDList;
        public IntPtr lpClass;
        public IntPtr hKeyClass;
        public int dwHotKey;
        public IntPtr hIcon_hMonitor;
        public IntPtr hProcess;
    }

    public struct ShellExecuteInfo {
        public ShellExecuteHookFlags Mask;
        public IntPtr hWnd;
        public String Verb;
        public String File;
        public String Parameters;
        public String Directory;
        public int ShowMode;
        public IntPtr hInstApp;
        public IntPtr IDList;
        public String Class;
        public IntPtr hKeyClass;
        public int HotKey;
        public IntPtr hIcon;
        public IntPtr hProcess;
    }

    #endregion

    #region - IShellExecuteHook -

    [Guid("000214F5-0000-0000-C000-000000000046")]
    [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    [ComImport]
    public interface IShellExecuteHookA {

        [PreserveSig]
        int Execute(ref SHELLEXECUTEINFO_ pei);

    }

    [Guid("000214FB-0000-0000-C000-000000000046")]
    [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    [ComImport]
    public interface IShellExecuteHookW {

        [PreserveSig]
        int Execute(ref SHELLEXECUTEINFO_ pei);

    }

    #endregion

#endif

}
